òɾۿûѧϰʹá
ԭַhttps://www.joinquant.com/post/11165

ԭһ˵ʽ鵽ԭĺ߽ۡ


ԭĲԴ£

# 뺯
import jqdata
import talib
import pandas as pd
import numpy as np
import datetime
from datetime import timedelta
import math
from numpy import nan

# ʼ趨׼ȵ
def initialize(context):
    # 趨300Ϊ׼
    set_benchmark('000001.XSHG')
    # ̬Ȩģʽ(ʵ۸)
    set_option('use_real_price', True)
    # ݵ־ log.info()
    log.info('ʼʼȫֻһ')
    # ˵orderϵAPIıerror͵log
    # log.set_level('order', 'error')
    g.num_stock = 10
    g.index = '000001.XSHG'
    g.index2 = '000300.XSHG'#300
    g.index8 = '399006.XSHE'#ҵָ
    # g.index2 = '000016.XSHG'#֤50
    # g.index8 = '399333.XSHE'#СR 
    g.risk_ratio = 0.10
    ### Ʊ趨 ###
    # ƱÿʽʱǣʱӶ֮ʱӶ֮ǧ֮һӡ˰, ÿʽӶͿ5Ǯ
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    run_monthly(rebalence,1,time = '14:50')

    
## ǰк     
# def before_trading_start(context):
    
    
## ʱк
def handle_data(context, data):
    if market_not_safe(g.index2,g.index8):
        # if len(context.portfolio.positions) >0:
        clear_position(context)
        return
    # if g.days%g.period == 0:
    #     if [context.current_dt.hour,context.current_dt.minute] == [14,50]:
        # rebalence(context)
    # g.days = g.days+1
    # for stock in context.portfolio.positions:
    #     if can_sell(stock):
    #         order_target_value(stock,0)
 
def rebalence(context):
    # if not market_not_safe(g.index2,g.index8):
    
    stocklist = select_stock(context)
    #
    for stock in context.portfolio.positions:
        if stock not in stocklist:
            order_target_value(stock,0)
    stock_values = calPosition(context,stocklist)
    for stock in stock_values:
        curPrice = attribute_history(stock, 1, '1m', ('close'),fq='pre')['close'].values
        curValue = context.portfolio.positions[stock].total_amount * curPrice
        target_value = stock_values[stock]
        if abs(target_value - curValue)>0.2:
            order_target_value(stock,target_value)
    
def select_stock(context):
    stocklist = get_index_stocks(g.index)
    stock_list = filter_specials(stocklist)
    stock_list = filter_new_and_sub_new(stock_list)
    stock_list = filter_big_amout_of_increase(stock_list)
    factor_dict = {}
    for stock in stock_list:
        temp = []
        temp.append(get_smart_money_factor(stock))
        factor_dict[stock] = temp
    df_factor = pd.DataFrame(factor_dict).T 
    df_factor = df_factor.dropna()
    df_factor.columns = ['smart_money_factor']
    df = df_factor.sort('smart_money_factor')
    print df.head()
    # stock_list = list(df.index.values)[:int(len(df)*0.1)]
    stock_list = list(df.index.values)[:10]
    
    return stock_list
    

def filter_big_amout_of_increase(stocklist,ratio = 0.2):
    stock_dict = {}
    for stock in stocklist:
        stock_dict[stock] = get_growth_rate(stock)
    sort_list = sorted(stock_dict.items(),key = lambda x:x[1])
    stock_list = sort_list[:int(len(sort_list)*(1-ratio))]
    stock_list = [stock[0] for stock in stock_list]
    return stock_list

def filter_new_and_sub_new(stocklist,days = 60):
    stock_list = []
    for stock in stocklist:
        start_date = get_security_info(stock).start_date
        if (datetime.date.today()-start_date)>timedelta(60):
            stock_list.append(stock)
    return stock_list



def get_smart_money_factor(stock,count_day = 1):
    
    df = attribute_history(stock,count_day*230,'1m',['open','close','volume'])
    df['zdf'] = abs(df['close']/df['open']-1)
    df['smart'] = df['zdf']/(df['volume'].apply(math.sqrt))
    df = df.sort('smart',ascending = False)
    df['cum_vol'] = df['volume'].cumsum()
    df['cum_vol'] = df['cum_vol']/df.ix[-1,'cum_vol']
    df_smart = df[df['cum_vol']<=0.2]
    all_vol = df['volume'].sum()
    all_smartvol = df_smart['volume'].sum()
    VWAP_smart = (df_smart['volume']*df_smart['close']/all_smartvol).sum()
    VWAP_all = (df['volume']*df['close']/all_vol).sum()
    try:
        factor = VWAP_smart/VWAP_all
    except:
        factor = nan
    return factor



    
def filter_specials(stock_list):
    curr_data = get_current_data()
    stock_list = [stock for stock in stock_list if \
                  (not curr_data[stock].paused)  # δͣ
                  and (not curr_data[stock].is_st)  # ST
                  and ('ST' not in curr_data[stock].name)
                  and ('*' not in curr_data[stock].name)
                  and ('' not in curr_data[stock].name)
                  and (curr_data[stock].low_limit < curr_data[stock].day_open < curr_data[stock].high_limit)  # δǵͣ
                  ]

    return stock_list

def market_not_safe(index2,index8):
    gr_index2 = get_growth_rate(index2)
    gr_index8 = get_growth_rate(index8)
    if gr_index2 <= 0 and  gr_index8 <= 0:
        return True

def get_growth_rate(security, n=20):
    lc = get_close_price(security, n)
    c = get_close_price(security, 1, '1m')
    
    #жǷΪ
    if not isnan(lc) and not isnan(c) and lc != 0:
        return (c - lc) / lc
    else:
        log.error("ݷǷ, security: %s, %d̼: %f, ǰ: %f" %(security, n, lc, c))
        return 0
        

def can_buy(security,short=5,long=20):
    #Ƿͷ
    ma_short = attribute_history(security, short, '1d', ('close'), True).mean()['close']
    ma_long = attribute_history(security, long, '1d', ('close'), True).mean()['close']
    cur_price = get_close_price(security,1,'1m')
    yes_price = get_close_price(security,1)
    if ma_short >= ma_long and cur_price > yes_price:
        return True
        




def get_close_price(security, n, unit='1d'):
    return attribute_history(security, n, unit, ('close'), True,fq='pre')['close'][0]
   
def clear_position(context):
    if len(context.portfolio.positions)>0:
        for stock in context.portfolio.positions:
            order_target_value(stock,0)
        log.info('ֹ,ȫ')


def calPosition(context, buylist):
    # ÿε֣ positionAdjustFactor ƳܵķգʧΪܲλ * positionAdjustFactor
    positionAdjustValue = context.portfolio.total_value * g.risk_ratio
    Ajustvalue_per_stock = float(positionAdjustValue)/len(buylist)

    hStocks = history(1, '1m', 'close', buylist, df=False)

    risk_value = {}
    # Ϻ ATR˴ʽƽ䡣
    for stock in buylist:
        curATR = 2*float(fun_getATR(stock))
        if curATR != 0 :
            risk_value[stock] = hStocks[stock]*Ajustvalue_per_stock/curATR
        else:
            risk_value[stock] = 0

    total_value = sum([risk_value[stock] for stock in risk_value])
    if total_value > context.portfolio.total_value:
        tempdict = {}
        for stock in buylist:
            tempdict[stock] = context.portfolio.total_value*(risk_value[stock]/total_value)
        risk_value = tempdict
    return risk_value   


def fun_getATR(stock):
    ATRlag = 14

    # ATRKeltner Band 
    try:
        hStock = attribute_history(stock, ATRlag+10, '1d', ('close','high','low') , df=False)
    except:
        log.info('%s ȡʷʧ' %stock)
        return 0
    close_ATR = fun_normalizeData(hStock['close'])
    high_ATR = fun_normalizeData(hStock['high'])
    low_ATR = fun_normalizeData(hStock['low'])
    try:
        ATR = talib.ATR(high_ATR, low_ATR, close_ATR, timeperiod=ATRlag)
    except:
        return 0

    return ATR[-1]

def fun_normalizeData(myData):
    # ȥֵ
    std = np.std(myData)
    MA = np.mean(myData)
    for i in range(len(myData)):
        if myData[i] > MA + 3*std:
            myData[i] = MA + 3*std
        elif myData[i] < MA - 3*std:
            myData[i] = MA - 3*std
    return myData    

